/***************************************************
 ** Create by Hasaki on 2021/11/27.
 ** This file is part of the CSTL project.
 ** This file follows version 3 of GNU License.
 ** About GNU, see <https://www.gnu.org/licenses/>.
 **
 ** 本文件由Hasaki(间宫羽咲sama)于2021年11月27日创建。
 ** 本文件是CSTL(C-STL)项目的一部分。
 ** 本文件遵从GNU-v3协议。
 ** 关于GNU协议，见<https://www.gnu.org/licenses/>。
 ***************************************************/
#ifndef HASAKI_BUFFER_H
#define HASAKI_BUFFER_H   // HskBuffer.h

#include <stdio.h>
#include <malloc.h>
#include <string.h>       // To include memcpy
#include <stdint.h>       // To include size_t, uint_8
#include "HskUtil.h"

/** -- final editor: Hasaki at 2021/11/27
 * @brief Buffer类
 * 本类储存Buffer类的数据成员和操作函数集合_obj
 * 不建议存指针，而是存类本身，因为析构函数不会free掉指针指向的对象
 */
typedef struct _Buffer {
  // data，可看作char []，要求begin<=read<=end<=last
  char *_begin;  // begin指针，指向使用空间的头
  char *_read;   // read指针，指向已读空间的尾
  char *_end;    // end指针，指向已写空间的尾
  char *_last;   // 指向分配空间的尾
} Buffer;

/** -- final editor: Hasaki at 2021/11/28
 * 我们约定typesize代表sizeof(type)，_type代表容器里存的数据类型
 * _this代表被操作对象的this指针，size代表已用空间，capa代表最大容量
 * Buffer类相关的接口函数如下——
 * BufCreate(typesize, size, capa);       // Buffer的构造函数
 * BufClean(_pthis);                      // Buffer的析构函数
 * BufDelete(_pthis);                     // Buffer的析构函数，析构后将buf指针置为NULL
 * BufReCapa(_this, newCapa);             // 将Buffer的最大容量capa重置为newCapa，会分配一段新的空间
 * BufReSize(_this);                      // 清理已读空间Buffer的已读空间
 * BufHandleAll(_this, handle);           // 对于Buffer内的元素都执行函数handle
 * BufPush(_this, val);                   // 往Buffer的end处push back一个字符val
 * BufPushSlice(_this, elemBeg, elemEnd); // 往Buffer的end处push back一个[elemBeg, elemEnd)的内容
 * BufReadBuf(_this, buf, N);             // 将buf未读的[read, read+N]读到_this末端，读完buf->read自增N
 * BufDelN(_this, _N);                    // 将Buffer的[size - N, size)的元素置0，并size减少N
 * BufGet(_this, N);                      // 返回指向(this->begin)[N]的指针
 * BufUnreadGet(_this, N);                // 返回指向(this->read)[N]的指针
 * BufGetUnreadSize(_this);               // 返回Buffer的未读空间
 * BufGetSize(_this);                     // 返回Buffer的已用空间
 * BufGetCapa(_this);                     // 返回Buffer的容量
 * BufDispMsg(_this);                     // 显示自己的unreadSize, capacity, typesize
 * BufDispAllString(_this);               // 以字符串格式显示整个Buffer的空间
 * BufDispUnreadString(_this);            // 以字符串格式显示整个Buffer的未读空间
 * BufDispAllChar(_this);                 // 逐字符显示整个Buffer从beg到end的全部字符
 * BufDispAllInt(_this);                  // 逐字符以int格式显示整个Buffer从beg到end的全部字符的值
 */

/** -- final editor: Hasaki at 2021/11/27
 * @brief   BufCreate构造函数
 * @details 构造capacity大的Buffer类，初值为0
 * @note    伪代码如下：
 *          std::Buffer<char> buf;
 *          buf.reserve(capacity);
 *          return &buf;
 * @param[in] capacity: 初始预分配的容量数capacity
 * @retval  指向被创建的结构体的指针
 * @code
 *  // 创建42字节的Buffer类
 *  Buffer *buf = BufCreate(42);
 * @endcode
 */
Buffer* BufCreate(const size_t capacity);

/** -- final editor: Hasaki at 2021/11/27
 * @brief   BufClean析构函数
 * @details 清理buf对应的资源
 * @code
 *  // 清理Buf指向的资源，执行完记住把Buffer *置为NULL
 *  Buffer *buf1 = BufCreate(42);
 *  BufClean(buf1);
 *  buf1 = NULL;
 *  // 清理Buf指向的资源，执行完buf2就被free掉了，不应再使用
 *  Buffer buf2 = *BufCreate(42);
 *  BufClean(&buf2);
 * @endcode
 */
void BufClean(Buffer *_this);

/** -- final editor: Hasaki at 2021/11/29
 * @brief   BufDelete析构函数，析构后将Vec指针置为NULL
 * @details 相当于执行VecDelete再将自己置NULL
 * @code
 *  Buffer *buf1 = BufCreate(42);
 *  // 第一种清理方式
 *  BufDelete(&buf1);
 *  // 这等价于第一种清理方式
 *  BufClean(buf1);
 *  buf1 = NULL;
 * @endcode
 */
void BufDelete(Buffer **_pthis);

/** -- final editor: Hasaki at 2021/11/27
 * @brief   将capacity扩容/缩减到指定的newCapa大小
 * @details 扩容后只保留[read:end]部分，[begin:read]部分将会被删掉
 * @warning 如果newCapa < unreadSize，则只保留[read:read + newCapa]
 * @param[in] newCapa: 强制转化为的新容量
 * @note    伪代码如下：
 *          buf = buf[read:end];
 *          buf.reserve(newCapa);
 */
void BufReCapa(Buffer *const _this, const size_t newCapa);

/** -- final editor: Hasaki at 2021/11/27
 * @brief   清理已读空间
 * @note    伪代码如下：
 *          buf = buf[read:end];
 */
void BufReSize(Buffer *const _this);

/** -- final editor: Hasaki at 2021/11/27
 * @brief   用handle对buf里的每一个元素进行操作
 * @details 因为传的是函数指针，不如内联优化效率高，建议手动展开
 * @note    伪代码如下：
 *          seq = 0;
 *          for (auto *it : buf)
 *              handle(buf, it, seq ++);
 * @param[in] handle: 对于每一个元素进行遍历操作
 * @code
 *  // TODO: examples codes
 * @endcode
 */
void BufHandleAll(Buffer *const _this, void (*handle)(Buffer *const, char *, size_t));

/** -- final editor: Hasaki at 2021/11/27
 * @brief   往this->end处push一个val
 * @param[in] val: 要push进去的元素
 * @code
 *  // 例：往Buf里push一个'c'
 *  BufPush(buf, 'c');
 * @endcode
 */
void BufPush(Buffer *const _this, const char val);

/** -- final editor: Hasaki at 2021/11/29
 * @brief   往this->end处push一个[elemBeg, elemEnd)切片
 * @param[in] elemBeg: 指向要push进去的elem的头指针
 * @param[in] elemEnd: 指向要push进去的elem的尾指针
 * @code
 *  // 例：往buf2里push一个buf1
 *  Buffer *buf1, *buf2;
 *  BufPushSlice(buf2, buf1->_begin, buf2->_end);
 * @endcode
 */
void BufPushSlice(Buffer *const _this, const char *elemBeg, const char *elemEnd);

/** -- final editor: Hasaki at 2021/11/29
 * @brief   往this->end处push一个buf[read:read+N]，并使得buf->_read自增N
 * @param[in] buf: 待读的Buffer
 * @param[in] N  : 要读取的字节长度
 * @code
 *  // 例：往buf2里读入buf1的全部未读字节
 *  Buffer *buf1, *buf2;
 *  BufPushSlice(buf2, buf1, BufGetUnreadSize(buf1));
 * @endcode
 */
void BufReadBuf(Buffer *const _this, Buffer *const buf, const int N);

/** -- final editor: Hasaki at 2021/11/27
 * @brief   删掉end末尾N个元素（置0）
 * @param[in] N: 删掉末尾N个元素
 * @code
 *  // 例：删除vec末尾5个元素
 *  BufDelN(buf, 5);
 * @endcode
 */
void BufDelN(Buffer *const _this, const size_t _N);

/** -- final editor: Hasaki at 2021/11/29
 * @brief   返回char *类型指向(buf->_begin)[N]的指针
 * @retval  返回buf->begin的第N个元素
 * @code
 *  // 例1：获取buf1第2个元素
 *  printf("buf1[2] = %lld\n", *BufGet(buf1, 2));
 * @endcode
 */
char* BufGet(const Buffer *const _this, const size_t N);

/** -- final editor: Hasaki at 2021/11/29
 * @brief   返回char *类型指向(buf->_read)[N]的指针
 * @retval  返回buf->read的第N个元素
 * @code
 *  // 例1：获取buf1未读的第2个元素
 *  printf("buf1[read+2] = %lld\n", *BufUnreadGet(buf1, 2));
 * @endcode
 */
char* BufUnreadGet(const Buffer *const _this, const size_t N);

/** -- final editor: Hasaki at 2021/11/27
 * @brief   获取buf的unreadSize = end - read
 * @retval  返回buf的未读空间size
 */
size_t BufGetUnreadSize(const Buffer *const _this);

/** -- final editor: Hasaki at 2021/11/27
 * @brief   获取Buf的size = end - begin
 * @retval  返回buf的已用空间size
 */
size_t BufGetSize(const Buffer *const _this);

/** -- final editor: Hasaki at 2021/11/27
 * @brief 获取buf的capacity = last - begin
 * @retval  返回buf的最大容量capacity
 */
size_t BufGetCapa(const Buffer *const _this);

/** -- final editor: Hasaki at 2021/11/27
 * @brief 显示自己的unreadSize, size, capacity
 */
void BufDispMsg(const Buffer *const _this);

/** -- final editor: Hasaki at 2021/11/27
 * @brief 以string格式显示整个buffer[begin:end]
 */
void BufDispAllString(const Buffer *const _this);

/** -- final editor: Hasaki at 2021/11/27
 * @brief 以string格式显示未读的buffer[read:end]
 */
void BufDispUnreadString(const Buffer *const _this);

/** -- final editor: Hasaki at 2021/11/28
 * @brief 逐字符显示整个buffer从beg到end的全部字符
 * @param[in] beg: 显示范围的头指针
 * @param[in] end: 显示范围的尾指针
 */
void BufDispAllChar(const Buffer* const _this, const char* beg, const char* const end);

/** -- final editor: Hasaki at 2021/11/28
 * @brief 逐字符以int格式显示整个buffer从beg到end的全部字符的值
 * @param[in] beg: 显示范围的头指针
 * @param[in] end: 显示范围的尾指针
 */
void BufDispAllInt(const Buffer* const _this, const char* beg, const char* const end);

#endif  // HskBuffer.h
